package org.gw.building.interceptor;

import org.gw.ylc.base.context.RequestContext;
import org.gw.ylc.base.context.RequestContextHolder;
import org.gw.ylc.base.context.Roles;
import org.gw.ylc.base.data.PermissionContext;
import org.gw.ylc.base.model.UserInfo;
import org.gw.ylc.base.service.AuthenticateService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LoginInterceptor extends HandlerInterceptorAdapter implements InitializingBean {
    @Autowired
    private AuthenticateService authenticateService;
    @Autowired
    private List<RequestMappingHandlerAdapter> requestMappingHandlerAdapters;

    public void setAuthMode(String authMode) {
    }

    public LoginInterceptor() {
    }

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        HttpSession session = request.getSession(true);
        @SuppressWarnings("unchecked")
        List<UserInfo> users = (List<UserInfo>) session.getAttribute("_users_");
        // 没有登录
        if (CollectionUtils.isEmpty(users)) {
            // 尝试登录
            try {
                users = authenticateService.authenticate(request, "train");
            } catch (Exception e) {
                System.out.println(e.getMessage());
                response.sendRedirect(request.getContextPath() + "/accountError.html");
                return false;
            }
            // 登陆成功
            if (!CollectionUtils.isEmpty(users)) {
                for (UserInfo user : users) {
                    user.setPassword(null);
                }
                session.setAttribute("_users_", users);
                session.setAttribute("_current_user_", users.get(0));
            }
        }
        Map<String, Object> env = new HashMap<String, Object>();
        RequestContext context = new RequestContext();
        context.setPageRequest(buildPageRequest(request));
        if (!CollectionUtils.isEmpty(users)) {
            UserInfo currentUser = (UserInfo) session.getAttribute("_current_user_");
            context.setUser(currentUser);
            for (UserInfo user : users) {
                Roles r = Roles.getByOrdinal(user.getType());
                if (r != null) {
                    context.getAvailableRoles().add(r);// 可用角色
                }
            }
            RequestContextHolder.set(context);
            int i = currentUser.getType();
            switch (i) {
                case 0:
                    if (currentUser.isStudentRole()) {
                        PermissionContext.setCurrentRole(PermissionContext.STUDENT);
                    } else if (currentUser.isTeacherRole()) {
                        PermissionContext.setCurrentRole(PermissionContext.TEACHER);
                    }
                    break;
                case 1:
                    PermissionContext.setCurrentRole(PermissionContext.DEPARTMENT_ADMIN);
                    break;
                case 2:
                    PermissionContext.setCurrentRole(PermissionContext.SCHOOL_ADMIN);
                    break;
                case 3:
                    PermissionContext.setCurrentRole(PermissionContext.SCHOOL_ADMIN);
                    break;
                case 4:
                    PermissionContext.setCurrentRole(PermissionContext.BRANCH_ADMIN);
                    break;
                default:
                    break;
            }
            env.put("$user", currentUser);
        } else {
            context.setUser(UserInfo.ANONYMOUS);
            RequestContextHolder.set(context);
            env.put("$user", UserInfo.ANONYMOUS);
            PermissionContext.setCurrentRole(PermissionContext.TOURIST);
        }
        PermissionContext.setEnvironment(env);
        if (handler instanceof HandlerMethod) {
            HandlerMethod m = (HandlerMethod) handler;
            RequestPermission permission = m.getMethodAnnotation(RequestPermission.class);
            if (permission != null) {
                UserInfo user = RequestContextHolder.get().getUser();
                int type = user.getType();
                int[] value = permission.value();
                if (value != null) {
                    for (int v : value) {
                        if (v == type) {
                            return true;
                        }
                    }
                }
                if (type >= permission.min() && type <= permission.max())
                    return true;
                if (type == -1) {
                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
                } else
                    response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
                return false;
            }
        }
        return true;
    }

    private PageRequest buildPageRequest(HttpServletRequest request) {
        String pageNumber = request.getParameter("pageNumber");
        String pageSize = request.getParameter("pageSize");
        int pN = 0;
        int pS = 15;
        if (StringUtils.hasText(pageNumber)) {
            pN = Integer.parseInt(pageNumber);
        }
        if (StringUtils.hasText(pageSize)) {
            pS = Integer.parseInt(pageSize);
        }
        return new PageRequest(pN, pS);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        RequestContextHolder.remove();
        // ContextParamHolder.removeParams();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        for (RequestMappingHandlerAdapter adapter : requestMappingHandlerAdapters) {
            List<HttpMessageConverter<?>> messageConverters = adapter.getMessageConverters();
            for (HttpMessageConverter<?> c : messageConverters) {
                if (c instanceof StringHttpMessageConverter) {
                    StringHttpMessageConverter stringHttpMessageConverter = (StringHttpMessageConverter) c;
                    stringHttpMessageConverter.setSupportedMediaTypes(
                            Arrays.asList(new MediaType("text", "plain", Charset.forName("utf-8")), MediaType.ALL));
                }
            }

        }
    }

}
